package com.common.android.utils.download;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.FileLock;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.nd.android.u.allcommon.R;
import com.product.android.utils.LogUtils;

/**
 * ClassName:ProgressDownloadManager
 * Function: 显示进度的文件下载管理
 * Reason:	 
 * @author   cb		
 * @version  Ver 1.3.3_modularization
 * @Date	 2014	2014-2-11		上午11:03:35
 *
 * @see 	 
 */
public class ProgressDownloadManager {
	public interface onDonwloadListener{
		void onSuccess(File file);
		void onFail(int res,String reason);
		void onProgress(long cur,long total);
	}
	private onDonwloadListener mListener;
	private boolean mIsDisconnected=false;		//是否断线
	private boolean mShowProgress=true;			//是否显示进度
	private boolean mCancelDownload = false;    //取消下载
	private Map<String, String> mRequestPropertyHashMap;//http头参数
	
	/**
	 *
	 * @n<b>函数名称</b>     :addRequestProperty
	 * @brief  添加http头参数
	 * @see
	 * @since    Ver 1.0
	 * @param  @param key 参数名
	 * @param  @param value 参数值
	 * @return void
	 * @<b>作者</b>          :  PanYun
	 * @<b>创建时间</b>      :  2014-4-15上午10:06:10
	 */
	public void addRequestProperty(String key, String value){
		if(mRequestPropertyHashMap == null){
			mRequestPropertyHashMap = new HashMap<String, String>();
		}
		if(!mRequestPropertyHashMap.containsKey(key)){
			mRequestPropertyHashMap.put(key, value);
		}
	}
	/**
	 * @n<b>函数名称</b>     :setOnDownloadListener
	 * @brief 设置监听
	 * @version    Ver 1.3.3_modularization
	 * @param  @param listener
	 * @return void
	 * @<b>作者</b>          :  cb
	 * @<b>创建时间</b>      :  2014-2-11上午11:04:13      
	*/
	public void setOnDownloadListener(onDonwloadListener listener){
		mListener=listener;
	}
	
	/**
	 * @n<b>函数名称</b>     :showProgress
	 * @brief 是否显示时度
	 * @version    Ver 1.3.3_modularization
	 * @param  @param show
	 * @return void
	 * @<b>作者</b>          :  cb
	 * @<b>创建时间</b>      :  2014-2-11上午11:04:18      
	*/
	public void showProgress(boolean show){
		mShowProgress=show;
	}
	
	/**
	 * @n<b>函数名称</b>     :fetchFile
	 * @brief 下载文件
	 * @see
	 * @since    Ver 1.2
	 * @param  @param url 文件在服务器端的地址
	 * @param  @param file本地文件名
	 * @param  @return
	 * @return int
	 * @<b>作者</b>          :  cb
	 * @<b>创建时间</b>      :  2013-8-20下午3:09:41      
	*/
	public void startDownload(String url,File file){
		mIsDisconnected=false;
		
		if(file == null){			
			if (mListener!=null){
				mListener.onFail(R.string.fail_file_notfound,"");	
			}
			return;
		}
		
		HttpURLConnection urlConnection = null;
		BufferedInputStream in = null;
		FileOutputStream out = null;
		try {
			if (file.exists()){
				//如果文件已存在，删除旧文件
				file.delete();
			}
			file.createNewFile();
			//打开链接
			URL targetUrl = new URL(url);
			urlConnection = (HttpURLConnection) targetUrl.openConnection();
			//如果存在需要设置的http头值，则添加
			if(mRequestPropertyHashMap != null && mRequestPropertyHashMap.size() >0){
				Iterator<?> iter = mRequestPropertyHashMap.entrySet().iterator();
				while(iter.hasNext()){
					Map.Entry entry = (Map.Entry)iter.next();
					String key = (String)entry.getKey();
					String value = (String)entry.getValue();
					urlConnection.addRequestProperty(key, value);
				}
			}
			in = new BufferedInputStream(urlConnection.getInputStream(), 8192);
			FileLock fl = null;
			FileOutputStream fos = null;
			// 获取文件大小
			// 当前下载大小
			long curSize = 0;
			long notifySize=0;
			long totalSize=urlConnection.getContentLength();
			if (totalSize<=0){
				totalSize=getContentLength(urlConnection);
			}
			fos = new FileOutputStream(file.getPath());
			fl = fos.getChannel().tryLock();
			if (fl != null && fl.isValid()) {
				byte[] buffer = new byte[1024 << 2];
				int len1 = 0;
				while ((len1 = in.read(buffer)) > 0) {
					if (mIsDisconnected){
						//网络中断
						LogUtils.d("debug","network disconnected");
						fos.close();
						if (mListener!=null){
							mListener.onFail(R.string.fail_disconnect,"");	
						}
						return;
					}
					
					//取消下载
					if(this.mCancelDownload){
						break;
					}
					
					fos.write(buffer, 0, len1);
					if (totalSize>0){
						curSize += len1;
						if (((curSize-notifySize)<<4)>totalSize && mShowProgress){
							//当前进度增长值大于1/16，通知界面刷新一次（不需要频繁通知）
							if (mListener!=null){
								mListener.onProgress(curSize, totalSize);
							}
							notifySize=curSize;
						}
					}
				}
				fl.release();
				fos.close();
			}else{
				fos.close();
			}
		}catch (FileNotFoundException e){
			if (file!=null && file.exists()){
				file.delete();
			}
			if (mListener!=null){
				mListener.onFail(R.string.fail_file_notfound,"");	
			}
			return;
		}catch (Exception e) {
			if (mListener!=null){
				mListener.onFail(0,e.getMessage());	
			}
			return;
		}finally {
			if (urlConnection != null) {
				urlConnection.disconnect();
			}
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (final Exception e) {
			}
		}
		if (mListener!=null){
			mListener.onSuccess(file);
		}
	}
	
	/**
	 * @n<b>函数名称</b>     :getContentLength
	 * @brief 获取文件的长度
	 * @see
	 * @since    Ver 1.2
	 * @param  @param urlConnection
	 * @param  @return
	 * @return long
	 * @<b>作者</b>          :  cb
	 * @<b>创建时间</b>      :  2013-8-20下午3:10:58      
	*/
	private long getContentLength(HttpURLConnection urlConnection){
		String range=urlConnection.getHeaderField("Content-Range");
		//bytes 0-1879/1880
		String[] section = range.split("/");

		try {
			// Parse for the instance length
			return Long.parseLong(section[1]);
		} catch (NumberFormatException e) {
			LogUtils.d("debug",String.format("The HttpResponse contains an invalid instance-length: %s",range));
		}
		return 0;
	}

	/**
	 * 取消下载
	 * @n<b>函数名称</b>     :cancelDownload
	 * @brief
	 * @see
	 * @since    Ver 1.1
	 * @param  
	 * @return void
	 * @<b>作者</b>          :  黄永鑫
	 * @<b>创建时间</b>      :  2014-2-12下午5:50:01
	 */
	public void cancelDownload() {
		this.mCancelDownload = true;
	}
}
